package com.geoai.uimap.core.amap

import android.graphics.Color
import android.graphics.Point
import android.util.Log
import android.view.MotionEvent
import com.amap.api.maps.AMap
import com.amap.api.maps.model.*
import com.geoai.basiclib.utils.log.MyLogUtils
import com.geoai.uimap.api.IGEOMap
import com.geoai.uimap.api.IGEOMapOverlay
import kotlin.math.abs
import kotlin.math.roundToInt
import kotlin.math.sqrt

class GDOverlayExample(map: IGEOMap) : GDMapOverlay(map) {
    private var points: MutableList<LatLng> = ArrayList()
    private var line: Polyline? = null
    private var circleList: MutableList<Circle> = ArrayList()
    private var selectedPointIndex: Int = -1

    private val onMapClickListener = AMap.OnMapClickListener {
        selectedPointIndex = getSelectedPointIndex(it)
        if (selectedPointIndex < 0) {
            addPoint(it)
        }
    }

    private val onMapTouchListener = AMap.OnMapTouchListener {
        when (it.action) {
            MotionEvent.ACTION_DOWN -> {
                val latLng = getAMap().projection.fromScreenLocation(
                    Point(
                        it.x.roundToInt(),
                        it.y.roundToInt()
                    )
                )
                selectedPointIndex = getSelectedPointIndex(latLng)
            }
            MotionEvent.ACTION_MOVE -> {
                val latLng = getAMap().projection.fromScreenLocation(
                    Point(
                        it.x.roundToInt(),
                        it.y.roundToInt()
                    )
                )
                if (selectedPointIndex >= 0) {
                    movePoint(selectedPointIndex, latLng)
                }
            }
            MotionEvent.ACTION_UP -> {
                selectedPointIndex = -1
                getAMap().uiSettings.isScrollGesturesEnabled = true
            }
        }
    }

    private fun draw() {
        val lineOptions = PolylineOptions().addAll(points).width(LINE_WIDTH).color(LINE_COLOR)
        line = getAMap().addPolyline(lineOptions)
    }

    override fun show(): IGEOMapOverlay {
        draw()
        addTouchListener()
        return this
    }

    override fun destroy() {
        MyLogUtils.d("destroy overlay")
        removeTouchListener()
        points.clear()
        line?.remove()
        circleList.forEach {
            it.remove()
        }
    }

    private fun removeTouchListener() {
        getAMap().removeOnMapClickListener(onMapClickListener)
        getAMap().removeOnMapTouchListener(onMapTouchListener)
    }

    private fun addTouchListener() {
        getAMap().addOnMapClickListener(onMapClickListener)
        getAMap().addOnMapTouchListener(onMapTouchListener)
    }

    private fun getSelectedPointIndex(latLng: LatLng): Int {
        val point = getAMap().projection.toScreenLocation(latLng)
        val x = point.x
        val y = point.y
        for (index in 0 until points.size) {
            val current = points[index]
            val screenPoint = getAMap().projection.toScreenLocation(current)
            val xOffset = abs(screenPoint.x - x)
            val yOffset = abs(screenPoint.y - y)
            val distance = sqrt((xOffset * xOffset + yOffset * yOffset).toDouble())
            if (distance < 100) {
                Log.d("GD", "getSelectedPointIndex: $index")
                getAMap().uiSettings.isScrollGesturesEnabled = false
                return index
            }
        }

        return -1
    }

    private fun addPoint(point: LatLng) {
        MyLogUtils.d("add point")
        points.add(point)
        line?.points = points
        val circle = getAMap().addCircle(
            CircleOptions().center(point).radius(CIRCLE_RADIUS).fillColor(CIRCLE_COLOR)
                .strokeColor(LINE_COLOR).strokeWidth(CIRCLE_STROKE_WIDTH)
        )
        circleList.add(circle)
    }

    private fun movePoint(index: Int, latLng: LatLng) {
        MyLogUtils.d("move point")
        points[index] = latLng
        line?.points = points
        circleList[index].center = latLng

    }

    companion object {
        const val LINE_WIDTH = 8.0f
        const val LINE_COLOR = Color.BLUE
        const val CIRCLE_RADIUS = 12.0
        const val CIRCLE_STROKE_WIDTH = 8.0f
        const val CIRCLE_COLOR = Color.WHITE
    }
}